﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using ClassLibrary;
using ClassLibrary.Agent;
using ClassLibrary.Configuration.Switch;

namespace ControlNode
{
    internal class ConnectionController
    {
        private readonly RoutingController _rc;
        private readonly LinkResourceManager _lrm;
        private readonly Directory _dr;

        private const string Separator = "huiSiFtube";

        private Dictionary<String, SNP[]> paths = new Dictionary<string, SNP[]>();

        public ConnectionController(RoutingController rc, LinkResourceManager lrm, Directory dr)
        {
            _rc = rc;
            _lrm = lrm;
            _dr = dr;
        }

        public void ConnectionRequest(String src, String dst)
        {
            SNPP[] snpps = _rc.RouteTableQuery(src, dst);
            SNP[] snps = _lrm.getResPath(snpps);
            paths[src + Separator + dst] = snps;

            SendQueries(QueryType.Add, snps);
        }

        public void ConnectionTeardown(object src, object dst)
        {
            SNP[] snps = paths[src + Separator + dst];
            SendQueries(QueryType.Delete, snps);

        }

        private void SendQueries(QueryType queryType, SNP[] snps)
        {
            Logger.SetText(queryType.ToString() + " " + snps[0].NodeName + " " + snps[0].Port);
            for (int i = 1; i < snps.Count() - 1; i += 2)
            {
                Logger.SetText(queryType.ToString() + " " + snps[i].NodeName + " " + snps[i].Port + " " + snps[i + 1].Port);

                Socket node = _dr.Translate(snps[i].NodeName);
                int ingressPort = snps[i].Port;
                int egressPort = snps[i + 1].Port;

                var query = new Query()
                {
                    QueryType = queryType,
                    Record = new ConfSwitchingTable.Record()
                    {
                        Ingress = { PortId = ingressPort, VcId = 0 },
                        Egress = { PortId = egressPort, VcId = 0 }
                    }
                };

                var binaryFormatter = new BinaryFormatter();
                var memoryStream = new MemoryStream();
                binaryFormatter.Serialize(memoryStream, query);
                var serializedData = memoryStream.ToArray();
                node.BeginSend(serializedData, 0, serializedData.Length, SocketFlags.None,
                null, null);
            }
            Logger.SetText(queryType.ToString() + " " + snps[snps.Count() - 1].NodeName + " " + snps[snps.Count() - 1].Port);
        }
    }
}
